/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openFuyao is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package utils

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
)

const fileMode = 0644 // 普通文件权限：所有者可读、写，组和其他用户只读

func TestNewPathExpander(t *testing.T) {
	expander := NewPathExpander()

	if expander == nil {
		t.Error("Expected PathExpander instance, got nil")
	}
	if !expander.ExpandWildcards {
		t.Error("Expected ExpandWildcards to be true by default")
	}
	if !expander.ExpandEnvVars {
		t.Error("Expected ExpandEnvVars to be true by default")
	}
}

func TestExpandPathsEmptyList(t *testing.T) {
	expander := NewPathExpander()

	result, err := expander.ExpandPaths([]string{})

	assertNoError(t, err)
	assertEqual(t, len(result), 0)
}

func TestExpandPathsSinglePath(t *testing.T) {
	expander := NewPathExpander()

	result, err := expander.ExpandPaths([]string{"/tmp"})

	assertNoError(t, err)
	assertEqual(t, len(result), 1)
	assertEqual(t, result[0], "/tmp")
}

func TestExpandPathNoWildcards(t *testing.T) {
	expander := NewPathExpander()

	result, err := expander.ExpandPath("/tmp/test")

	assertNoError(t, err)
	assertEqual(t, len(result), 1)
	assertEqual(t, result[0], "/tmp/test")
}

func TestExpandPathWithWildcards(t *testing.T) {
	tempDir := createTestFiles(t)
	defer cleanupTestFiles(t, tempDir)

	expander := NewPathExpander()

	pattern := filepath.Join(tempDir, "*.txt")
	result, err := expander.ExpandPath(pattern)

	assertNoError(t, err)
	assertEqual(t, len(result), 2) // file1.txt and file2.txt
}

func TestExpandPathWildcardNoMatches(t *testing.T) {
	expander := NewPathExpander()

	result, err := expander.ExpandPath("/nonexistent/*.txt")

	assertNoError(t, err)
	assertEqual(t, len(result), 0)
}

func TestExpandEnvironmentVariablesHomeDirectory(t *testing.T) {
	expander := NewPathExpander()

	// 测试家目录展开
	result := expander.expandEnvironmentVariables("~")
	assertNotEqual(t, result, "~")

	result = expander.expandEnvironmentVariables("~/test")
	assertTrue(t, strings.HasPrefix(result, "/"))
	assertTrue(t, strings.HasSuffix(result, "/test"))
}

func TestExpandEnvironmentVariablesEnvVars(t *testing.T) {
	expander := NewPathExpander()

	// 设置测试环境变量
	err := os.Setenv("TEST_VAR", "test_value")
	if err != nil {
		return
	}
	defer os.Unsetenv("TEST_VAR")

	result := expander.expandEnvironmentVariables("$TEST_VAR/path")
	assertEqual(t, result, "test_value/path")

	result = expander.expandEnvironmentVariables("${TEST_VAR}/path")
	assertEqual(t, result, "test_value/path")
}

func TestContainsWildcard(t *testing.T) {
	testCases := []struct {
		path     string
		expected bool
	}{
		{"/tmp/*.txt", true},
		{"/tmp/file?.txt", true},
		{"/tmp/file[0-9].txt", true},
		{"/tmp/normal.txt", false},
		{"/tmp/directory/", false},
		{"", false},
	}

	for _, tc := range testCases {
		t.Run(tc.path, func(t *testing.T) {
			result := containsWildcard(tc.path)
			assertEqual(t, result, tc.expected)
		})
	}
}

// createTestFiles 创建测试文件
func createTestFiles(t *testing.T) string {
	tempDir, err := os.MkdirTemp("", "path-expander-test-*")
	assertNoError(t, err)

	// 创建测试文件
	createTestFile(t, tempDir, "file1.txt")
	createTestFile(t, tempDir, "file2.txt")
	createTestFile(t, tempDir, "file3.go")
	createTestFile(t, tempDir, "data.json")

	return tempDir
}

// createTestFile 创建单个测试文件
func createTestFile(t *testing.T, dir, filename string) {
	filePath := filepath.Join(dir, filename)
	err := os.WriteFile(filePath, []byte("test content"), fileMode)
	assertNoError(t, err)
}

// cleanupTestFiles 清理测试文件
func cleanupTestFiles(t *testing.T, dir string) {
	err := os.RemoveAll(dir)
	if err != nil {
		t.Logf("Warning: Failed to cleanup test files: %v", err)
	}
}

// assertNoError 检查没有错误
func assertNoError(t *testing.T, err error) {
	t.Helper()
	if err != nil {
		t.Fatalf("Expected no error, got: %v", err)
	}
}

// assertNotEqual 检查不相等
func assertNotEqual(t *testing.T, actual, expected interface{}) {
	t.Helper()
	if actual == expected {
		t.Fatalf("Expected not equal, but both are %v", actual)
	}
}

// assertTrue 检查为真
func assertTrue(t *testing.T, condition bool) {
	t.Helper()
	if !condition {
		t.Fatal("Expected condition to be true")
	}
}

// assertEqual 检查相等
func assertEqual(t *testing.T, actual, expected interface{}) {
	t.Helper()
	if actual != expected {
		t.Fatalf("Expected %v, got %v", expected, actual)
	}
}
